import { ir, native, HomeCheckIrHint, getIrLocationOfToken } from 'qvog-dsl';
import { CheckerUtils } from '../../../Index';

const SEVERITY = 2;
const DOC_PATH = 'docs/no-async-promise-executor.md';
const DESCRIPTION = 'Promise executor functions should not be async';
const PROMISE_NAME = 'async';

export default native<HomeCheckIrHint>({ use: 'ir' })()
    .match((stmt): stmt is ir.ArkInvokeStmt => {
        return stmt instanceof ir.ArkInvokeStmt;
    })
    .when((stmt): boolean => {
        const invokeExpr = CheckerUtils.getInvokeExprFromStmt(stmt);
        if (!invokeExpr) {
            return false;
        }
        if (!(stmt.getInvokeExpr() instanceof ir.ArkInstanceInvokeExpr)) {
            return false;
        }
        if (stmt.toString().includes('Promise.constructor()')) {
            const code = stmt.getOriginalText() ?? '';
            if (findSpecialStatement(code)) {
                return true;
            }
        }
        return false;
    })
    .report((stmt, {api}): void => {
        api.report({
            location: getIrLocationOfToken(stmt, PROMISE_NAME),
            severity: SEVERITY,
            description: DESCRIPTION,
            docPath: DOC_PATH,
        })
    });

function findSpecialStatement(code: string): boolean {
    if (!code) return false;
    const patterns = [
        /new\s+Promise\s*\(\s*async/g,
        /new\s+Promise\s*\(\s*\(*\s*async/g,
        /new\s+Promise\s*\(\s*.*?\(\s*resolve\s*,\s*reject\s*\)\s*=>\s*{[\s\S]*?setTimeout\s*\(/g,
        /new\s+Promise\s*\(\s*.*?\(\s*resolve\s*,\s*reject\s*\)\s*=>\s*{[\s\S]*?await\s+/g
    ];
    return patterns.some(regex => regex.test(code));
}
